import { hasOwn, isPlainObject } from "../util"

/** 
 * 定义对象属性的 getter setter
 * 通过 setter 捕捉属性的值的变化
 */
export function defineReactive (
  obj: Object,
  key: string
) {
  let val = obj[key]
  // val 如果是一个对象，也要处理成可响应的对象
  observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      return val
    },
    set: function reactiveSetter (newVal) {
      if (newVal === val || (newVal !== newVal && val !== val)) {
        // 这个是不是很奇怪， 提示 NaN === NaN 为 false, NaN !== NaN 为 true 。
        // 如果一个变量不等于自己，说明这个变量的值为 False
        // 判断新旧值是否一致而已
        return
      }
      // 这里我们就先写个 console.log 吧
      console.log(obj, `的属性 ${key} 的值从 ${val} 变为 ${newVal}`)
      val = newVal
    }
  })
}

/**
 * 响应式对象的观察者
 */
export class Observer {
  constructor (value: any) {
    this.walk(value)
  }
  walk (obj: object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }
}

export function observe (value: any) {
  if (isPlainObject(value)) { // 👈 这个函数名称很值得讨论
    // 这里创建了一个对象 Observer 来管理这个响应式对象
    // 响应式对象的转化过程也是在 Observer 中完成的
    new Observer(value)
  }
}
